﻿using BCCommon;
using BCCommon.TMS.Order;
using BCCommon.TMS.Transport;
using BCData.TMS.Order.OrderAssignRecord;
using BCDto.Common.ErrorMessage;
using BCDto.Location.Driver;
using BCDto.Location.Horseman;
using BCDto.TMS.Order;
using BCDto.TMS.Order.OrderPool;
using BCDto.TMS.OrderExtentionGoodsChecklist;
using BCDto.TMS.OrderFreightRecord;
using BCDto.TMS.OrderPackingRecord;
using BCDto.TMS.OrderSpecificServiceRecord;
using BCService.TMS.Location;
using BCService.TMS.Location.Driver;
using BCService.TMS.Order;
using BCService.TMS.Order.Order;
using BCService.TMS.OrderExtentionGoodsChecklist;
using BCService.TMS.OrderFreightRecord;
using BCService.TMS.OrderPackingRecord;
using BCService.TMS.OrderSpecificServiceRecord;
using BCTMSRESTful.Configs;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BCTMSRESTful.Controllers.Management.TMS.Order
{
    /// <summary>
    /// 订单
    /// </summary>
    [ApiExplorerSettings(GroupName = "TMSAdmin")]
    [Route("api/v1/sim/[controller]")]
    public class OrderController : ManagementBaseController
    {
        private readonly IOrderProcessService orderProcessService;
        private readonly IOrderPoolService orderPoolService;
        private readonly IOrderExtentionGoodsChecklistService orderExtentionGoodsChecklistService;
        private readonly IOrderFreightRecordService orderFreightRecordService;
        private readonly IOrderSpecificServiceRecordService orderSpecificServiceRecordService;
        private readonly IOrderPackingRecordService orderPackingRecordService;
        private readonly ILocationService locationService;
        public OrderController(IOrderProcessService orderProcessService,
            IOrderPoolService orderPoolService,
            IOrderExtentionGoodsChecklistService orderExtentionGoodsChecklistService,
            IOrderFreightRecordService orderFreightRecordService,
            IOrderSpecificServiceRecordService orderSpecificServiceRecordService,
            IOrderPackingRecordService orderPackingRecordService,
            ILocationService locationService)
        {
            this.orderProcessService = orderProcessService;
            this.orderPoolService = orderPoolService;
            this.orderExtentionGoodsChecklistService = orderExtentionGoodsChecklistService;
            this.orderFreightRecordService = orderFreightRecordService;
            this.orderSpecificServiceRecordService = orderSpecificServiceRecordService;
            this.orderPackingRecordService = orderPackingRecordService;
            this.locationService = locationService;
        }

        #region 获取货物清单
        /// <summary>
        /// 获取货物清单
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <returns></returns>
        /// <response code="200">获取已接单订单列表。</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="401">请求需要认证或者认证信息已过期。</response>
        /// <response code="403">无权访问指定的功能。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        [HttpGet("[action]/{order_id}")]
        [ProducesResponseType(typeof(IEnumerable<OrderExtentionGoodsChecklistDto>), 200)]
        public IActionResult GoodsChecklist([FromRoute(Name = "order_id")] long orderId)
        {
            return this.Ok(this.orderExtentionGoodsChecklistService.GetList(orderId));
        }
        #endregion

        #region 获取订单费用清单
        /// <summary>
        /// 获取订单费用清单
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <returns></returns>
        /// <response code="200">获取订单费用清单。</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="401">请求需要认证或者认证信息已过期。</response>
        /// <response code="403">无权访问指定的功能。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        [HttpGet("[action]/{order_id}")]
        [ProducesResponseType(typeof(IEnumerable<OrderFreightRecordDto>), 200)]
        public IActionResult FreightRecord([FromRoute(Name = "order_id")] long orderId)
        {
            return this.Ok(this.orderFreightRecordService.GetList(orderId));
        }
        #endregion

        #region 获取订单特殊服务
        /// <summary>
        /// 获取订单特殊服务
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <returns></returns>
        /// <response code="200">获取订单特殊服务。</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="401">请求需要认证或者认证信息已过期。</response>
        /// <response code="403">无权访问指定的功能。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        [HttpGet("[action]/{order_id}")]
        [ProducesResponseType(typeof(IEnumerable<OrderSpecificServiceRecordDto>), 200)]
        public IActionResult SpecificService([FromRoute(Name = "order_id")] long orderId)
        {
            return this.Ok(this.orderSpecificServiceRecordService.GetList(orderId));
        }
        #endregion

        #region 获取订单包装材料
        /// <summary>
        /// 获取订单包装材料
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <returns></returns>
        /// <response code="200">获取订单包装材料。</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="401">请求需要认证或者认证信息已过期。</response>
        /// <response code="403">无权访问指定的功能。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        [HttpGet("[action]/{order_id}")]
        [ProducesResponseType(typeof(IEnumerable<OrderPackingRecordDto>), 200)]
        public IActionResult Packing([FromRoute(Name = "order_id")] long orderId)
        {
            return this.Ok(this.orderPackingRecordService.GetList(orderId));
        }
        #endregion


        #region 获取订单信息列表--分页--工作台使用
        /// <summary>
        /// 获取订单信息列表--分页--工作台使用
        /// </summary>
        /// <response code="200">订单列表</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(PageableList<OrderPoolDto>), 200)]
        public IActionResult PoolQuery([FromQuery(Name = "province_code")] string provinceCode,
            [FromQuery(Name = "city_code")] string cityCode,
            [FromQuery(Name = "county_code")] string countyCode,
            [FromQuery(Name = "assign_status")] OrderAssignHandleStatus? assignStatus = OrderAssignHandleStatus.Pending,
            [FromQuery(Name = "index")] int pageIndex = 1,
            [FromQuery(Name = "size")] int pageSize = 10)
        {
            return Ok(this.orderPoolService.GetOrders(this.Admin, provinceCode, cityCode, countyCode, assignStatus, null, null, null, null, pageIndex, pageSize));
        }
        #endregion

        #region 获取订单信息列表--分页
        /// <summary>
        /// 获取订单信息列表--分页
        /// </summary>
        /// <param name="orderNo">订单编号</param>
        /// <param name="vehicleNo">车牌号</param>
        /// <param name="provinceCode">省份编码</param>
        /// <param name="cityCode">城市编码</param>
        /// <param name="countyCode">区县编码</param>
        /// <param name="orderStatus">订单状态</param>
        /// <param name="goodsName">货物名称</param>
        /// <param name="endProvinceCode">目的地省份编码</param>
        /// <param name="endCityCode">目的地城市编码</param>
        /// <param name="endCountyCode">目的地区县编码</param>
        /// <param name="goodsWeightLeft">货物重量(吨)左区间值</param>
        /// <param name="goodsWeightRight">货物重量(吨)右区间值</param>
        /// <param name="vehicleTypeId">车型ID</param>
        /// <param name="transportBusinessType">业务类型(订单类型)</param>
        /// <param name="vehicleCategoryName">车辆分类</param>
        /// <param name="phone">手机号</param>
        /// <param name="start">开始时间</param>
        /// <param name="end">结束时间</param>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">每页数据条数</param>
        /// <response code="200">订单列表</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(PageableList<OrderDto>), 200)]
        public IActionResult Query([FromQuery(Name = "order_no")] string orderNo,
            [FromQuery(Name = "vehicle_no")] string vehicleNo,
            [FromQuery(Name = "province_code")] string provinceCode,
            [FromQuery(Name = "city_code")] string cityCode,
            [FromQuery(Name = "county_code")] string countyCode,
            [FromQuery(Name = "order_status")] OrderStatus? orderStatus,
            [FromQuery(Name = "goods_name")] string goodsName,
            [FromQuery(Name = "end_province_code")] string endProvinceCode,
            [FromQuery(Name = "end_city_code")] string endCityCode,
            [FromQuery(Name = "end_county_code")] string endCountyCode,
            [FromQuery(Name = "goods_weight_left")] decimal? goodsWeightLeft,
            [FromQuery(Name = "goods_weight_right")] decimal? goodsWeightRight,
            [FromQuery(Name = "vehicle_type_id")] int? vehicleTypeId,
            [FromQuery(Name = "business_type")] TransportBusinessType? transportBusinessType,
            [FromQuery(Name = "vehicle_category_name")] string vehicleCategoryName,
            [FromQuery(Name = "phone")] string phone,
            [FromQuery(Name = "start")] DateTime? start,
            [FromQuery(Name = "end")] DateTime? end,
            [FromQuery(Name = "index")] int pageIndex = 1,
            [FromQuery(Name = "size")] int pageSize = 10)
        {
            return Ok(this.orderProcessService.Query(this.Admin, orderNo, vehicleNo, provinceCode, cityCode, countyCode, orderStatus, goodsName, null, null,
                endProvinceCode, endCityCode, endCountyCode, goodsWeightLeft, goodsWeightRight, vehicleTypeId, transportBusinessType, vehicleCategoryName, phone, start, end, null, pageIndex, pageSize));
        }
        #endregion


        #region 订单指派司机
        /// <summary>
        /// 订单指派司机
        /// </summary>
        /// <param name="orderId">订单Id</param>
        /// <param name="driverId">车辆Id</param> 
        /// <param name="distance">路径规划距离</param>
        /// <response code="200">订单列表</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpPut("[action]")]
        [Log("订单指派司机")]
        [ProducesResponseType(typeof(bool), 200)]
        [ProducesResponseType(typeof(ErrorMessageDto), 400)]
        [ProducesResponseType(typeof(ErrorMessageDto), 500)]
        public IActionResult AssignDriver([FromQuery(Name = "order_id")] long orderId, [FromQuery(Name = "driver_id")] long driverId, [FromQuery(Name = "distance")] int? distance)
        {
            return Ok(this.orderProcessService.AssignDriver(orderId, driverId, distance, this.Admin));
        }


        #endregion

        #region 获取订单取货地附近车辆列表
        /// <summary>
        /// 获取订单取货地附近车辆列表
        /// </summary>
        /// <response code="200">附近车辆列表</response>
        /// <returns></returns>
        [HttpGet("[action]/{order_id}")]
        [ProducesResponseType(typeof(IEnumerable<DriverLocationNearDto>), 200)]
        public IActionResult QueryNearVehicles([FromRoute(Name = "order_id")] long orderId,
            [FromQuery(Name = "max_distance")] int maxDistance)
        {
            return Ok(this.locationService.QueryNearDrivers(orderId, maxDistance));
        }
        #endregion

        #region 根据车牌搜索车辆位置
        /// <summary>
        /// 根据车牌搜索车辆位置。
        /// </summary>
        /// <param name="vehicleNo">车牌号</param>
        /// <response code="200">车辆信息</response>
        /// <returns></returns>
        [HttpGet("[action]/{vehicle_no}/{order_id}")]
        [ProducesResponseType(typeof(DriverLocationBsonDto), 200)]
        public IActionResult SearchVehicleLocation([FromRoute(Name = "vehicle_no")] string vehicleNo)
        {
            var result = this.locationService.GetDriverLocationInfo(vehicleNo.Trim());
            return this.Ok(result);
        }
        #endregion

        #region 获取订单取货地附近骑手列表
        /// <summary>
        /// 获取订单取货地附近骑手列表
        /// </summary>
        /// <response code="200">附近骑手列表</response>
        /// <returns></returns>
        [HttpGet("[action]/{order_id}")]
        [ProducesResponseType(typeof(IEnumerable<HorsemanLocationNearDto>), 200)]
        public IActionResult QueryNearHorsemen([FromRoute(Name = "order_id")] long orderId,
            [FromQuery(Name = "max_distance")] int maxDistance)
        {
            return Ok(this.locationService.QueryNearHorsemen(orderId, maxDistance));
        }
        #endregion


        #region 根据车牌搜索骑手位置
        /// <summary>
        /// 根据车牌搜索骑手位置。
        /// </summary>
        /// <param name="vehicleNo">车牌号</param>
        /// <response code="200">骑手信息</response>
        /// <returns></returns>
        [HttpGet("[action]/{vehicle_no}/{order_id}")]
        [ProducesResponseType(typeof(DriverLocationBsonDto), 200)]
        public IActionResult SearchHorsemanLocation([FromRoute(Name = "vehicle_no")] string vehicleNo)
        {
            var result = this.locationService.GetHorsemanLocationInfo(vehicleNo.Trim());
            return this.Ok(result);
        }

        #endregion

        #region 订单指派
        /// <summary>
        /// 订单指派
        /// </summary>
        /// <param name="orderIds">订单Ids</param>
        /// <param name="vehicleId">车辆Id</param>
        /// <param name="isAggregate">是否总量订单</param>
        /// <param name="distance">路径规划距离</param>
        /// <response code="200">订单列表</response>
        /// <returns></returns>
        [HttpPut("[action]")]
        [Log("订单指派")]
        [ProducesResponseType(typeof(bool), 200)]
        public IActionResult AssignVehicle([FromQuery(Name = "order_ids")] long[] orderIds,
            [FromQuery(Name = "vehicle_id")] long vehicleId,
            [FromQuery(Name = "is_aggregate")] bool isAggregate,
            [FromQuery(Name = "distance")] int? distance)
        {
            return Ok(this.orderPoolService.AssignVehicle(orderIds, vehicleId, distance, this.Admin));
        }
        /// <summary>
        /// 订单指派
        /// </summary>
        /// <param name="orderIds">订单Ids</param>
        /// <param name="vehicleNo">车牌号</param>
        /// <param name="isAggregate">是否总量订单</param>
        /// <param name="distance">路径规划距离</param>
        /// <response code="200">订单列表</response>
        /// <returns></returns>
        [HttpPut("[action]/{vehicle_no}")]
        [Log("订单指派--指定车牌号")]
        [ProducesResponseType(typeof(bool), 200)]
        public IActionResult AssignVehicle([FromQuery(Name = "order_ids")] long[] orderIds,
            [FromRoute(Name = "vehicle_no")] string vehicleNo,
            [FromQuery(Name = "is_aggregate")] bool isAggregate,
            [FromQuery(Name = "distance")] int? distance)
        {
            return Ok(this.orderPoolService.AssignVehicle(vehicleNo, orderIds, distance, this.Admin));
        }
        #endregion



    }
}
